/*
 * Copyright (C) 2017 Pingan, Inc. All Rights Reserved.
 */

package com.pingan.haofang.searchcloud.web.index.validator;

import com.google.common.primitives.Chars;
import com.pingan.haofang.framework.common.functional.lang.control.validator.bo.ValidationError;
import com.pingan.haofang.framework.common.functional.lang.control.validator.bo.ValidationResult;
import com.pingan.haofang.searchcloud.common.validator.annotation.ValidHandler;
import com.pingan.haofang.searchcloud.index.constants.IndexDataSourceType;
import com.pingan.haofang.searchcloud.index.dto.IndexQueryResult;
import com.pingan.haofang.searchcloud.index.service.IndexService;
import com.pingan.haofang.searchcloud.web.index.vo.IndexDatasourceBuildVO;
import com.pingan.haofang.searchcloud.web.index.vo.IndexDatasourceVO;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.quartz.CronExpression;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerUtils;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * 索引构建相关校验
 *
 * @author zhangbi617
 * @date 08/05/2017
 */
@Component
public class IndexDatasourceValidator {

    private static final Logger LOGGER = LoggerFactory.getLogger(IndexDatasourceValidator.class);

    @Autowired
    private IndexService indexService;

    /**
     * 索引导入任务修改
     *
     * @param result
     * @param form
     */
    @ValidHandler
    public void createIndexDatasourceSettings(ValidationResult result, IndexDatasourceVO form) {

        if (form.getIncDatasourceType() != null && form.getIncDatasourceType()
                != IndexDataSourceType.NOT_SURPPORT.getValue()) {
            if (form.getIncDatasourceRpc() == null) {
                result.addError(ValidationError.of("incDatasourceRpc",
                        "indexDatasource.incDatasourceRpc.should.not.null"));
                return;
            }
        }

        IndexQueryResult indexQueryResult = indexService.queryBasicInfoById(form.getIndexId());
        if (indexQueryResult == null) {
            result.addError(ValidationError.of("indexId",
                    "indexDatasource.indexId.not.exist"));
        }

      /*  if (form.getIncDatasourceRpc() != null ) {
            switch (IndexDatasourceStatus.get(form.getIncDatasourceRpc().getBufferStatus())){
                case NORMAL:
                    if (form.getIncDatasourceRpc().getBufferSize() == null ) {
                        result.addError(ValidationError.of("incDatasourceRpc.bufferSize",
                                "indexDatasource.incDatasourceRpc.buffer.size.should.not.null"));
                    }
                    if (form.getIncDatasourceRpc().getMaxWaitTime() == null ) {
                        result.addError(ValidationError.of("incDatasourceRpc.maxWaitTime",
                                "indexDatasource.incDatasourceRpc.buffer.maxWaitTime.should.not.null"));
                    }
                    break;
                case DISABLE:
                    if (form.getIncDatasourceRpc().getBufferSize() != null ) {
                        result.addError(ValidationError.of("incDatasourceRpc.bufferSize",
                                "indexDatasource.incDatasourceRpc.buffer.size.should.null"));
                    }
                    if ( form.getIncDatasourceRpc().getMaxWaitTime() != null ) {
                        result.addError(ValidationError.of("incDatasourceRpc.maxWaitTime",
                                "indexDatasource.incDatasourceRpc.buffer.maxWaitTime.should.null"));
                    }
                    break;
                default:
                    break;
            }


        }*/


    }

    /**
     * 校验数据源全量设置
     *
     * @param result
     * @param request
     */
    @ValidHandler
    public void saveIndexDatasourceBuild(ValidationResult result, IndexDatasourceBuildVO request) {
        String cron = request.getCron();
        String incCron = request.getIncCron();

        // 校验cron表达式是否合法
        if (!CronExpression.isValidExpression(cron)) {
            result.addError(ValidationError.of("cron",
                    "indexDatasource.fullDatasourceRpc.cron.error"));
            return;
        }

        // 校验inc cron表达式是否合法
        if (!org.springframework.util.StringUtils.isEmpty(incCron) && !CronExpression.isValidExpression(incCron)) {
            result.addError(ValidationError.of("incCron",
                    "indexDatasource.incDatasourceRpc.cron.error"));
            return;
        }

        // 校验是否太频繁
        try {

            CronExpression cronExpression = new CronExpression(cron);

            // quatz配置可能里面包含* , / - ,在分钟的那一列不允许有
            String[] cronItems = StringUtils.split(cronExpression.getCronExpression(), " ");
            for (char exclude : Chars.asList('*', '-', '/', ',')) {
                if (cronItems[1].indexOf(exclude) != -1) {
                    result.addError(ValidationError.of("cron",
                            "indexDatasource.fullDatasourceRpc.cron.too.many"));
                }
            }


            CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                    .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)).build();

            if (cronTrigger instanceof CronTriggerImpl) {

                // 以下这行代码很慢，所以用前面判断某些特殊字符是否包含来做初次过滤
                List<Date> dateList = TriggerUtils.computeFireTimesBetween((CronTriggerImpl) cronTrigger,
                        null,
                        new Date(), DateUtils.addYears(new Date(), 1));

                // cron必须大于每小时一次，也就是一年要小于24*365次才行，
                if (dateList.size() >= 24 * 365) {
                    result.addError(ValidationError.of("cron",
                            "indexDatasource.fullDatasourceRpc.cron.too.many"));
                }
            }
        } catch (ParseException e) {
            LOGGER.error(e.getMessage(), e);
            result.addError(ValidationError.of("cron",
                    "indexDatasource.fullDatasourceRpc.cron.error"));
        }
    }

    /**
     * 读取校验
     *
     * @param result
     * @param indexId
     */
    @ValidHandler
    public void list(ValidationResult result, Long indexId) {

    }



}
